package com.bsoft.service.impl;

import com.bsoft.aop.annotation.MultiDataSourceTransactional;
import com.bsoft.controller.JSON.MedicareController;
import com.bsoft.mapper.business.MedicareMapper;
import com.bsoft.service.MedicareService;
import com.bsoft.utils.ConmonUtil;
import com.bsoft.utils.JSONUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import javax.lang.model.element.NestingKind;
import java.sql.Clob;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//MedicareMapper  @Select("select * from  yb_ty_js01  where mzzy=1 and fphm=#{fphm} ")
@Service
@EnableTransactionManagement
public class MedicareServiceImpl extends ConmonUtil implements MedicareService {
    private static Logger logger = LoggerFactory.getLogger(MedicareServiceImpl.class);

    @Autowired
    private MedicareMapper medicareMapper;


    /**
     * 医保数据补录
     */
    @Override
    @MultiDataSourceTransactional(transactionManagers = {"hisTransactionManager"})
    public String saveMedicareData(Map<String, Object> req) throws Exception {
        isNUll(req, Arrays.asList("MDTRT_ID", "SETL_ID", "PSN_NO"));
        //1.先判断 his是否能查的出来结算记录
        Map<String, Object> settRecordMap = medicareMapper.getMedicarSettRecord(req);
        if (!ObjectUtils.isEmpty(settRecordMap)) {
            throw new Exception("根据医保就诊ID[" + req.get("MDTRT_ID") + "],结算ID[" + req.get("SETL_ID") + "],人员编号[" + req.get("PSN_NO") + "]查询到存在医保结算记录!");
        }

        String infno ="";
        //2.当查询没有医保结算记录,就获取医保日志,目前只获取2207A/2304A/S2101 交易日志
        Map<String, Object> medicarLogMap = medicareMapper.getMedicarLog(req);
        Assert.notNull(medicarLogMap, "根据医保就诊ID[" + req.get("MDTRT_ID") + "],结算ID[" + req.get("SETL_ID") + "],人员编号[" + req.get("PSN_NO") + "]查询医保日志[HI_HIS_MI_LOGGER]为空!");
        Assert.notNull(medicarLogMap.get("OUTPUT"), "获取医保交易[2207A/2304A/S2101]交易日志[OUTPUT]返回为空!");
        Assert.notNull(medicarLogMap.get("INPUT"), "获取医保交易[2207A/2304A/S2101]交易日志[INPUT]返回为空!");

        //[2207A/2304A/S2101]输入参数
        String medicarInputStr = ClobToString((Clob)medicarLogMap.get("INPUT"));
        Map<String, Object> medicarInputMap = JSONUtil.toHashMap(medicarInputStr);
        Map<String, Object> inputDateMap = (Map<String, Object>)((Map<String, Object>)medicarInputMap.get("input")).get("data");

        //[2207A/2304A/S2101]输出信参数
        String medicarOutputStr =  ClobToString((Clob)medicarLogMap.get("OUTPUT"));
        Map<String, Object> medicarOutputMap = JSONUtil.toHashMap(medicarOutputStr);
        boolean infcode = StringUtils.equals("0", medicarOutputMap.get("infcode").toString());
        if (!infcode) throw new Exception("该次医保交易(结算ID[" + req.get("SETL_ID") + "])失败!");

        Map<String, Object> outputMap = ObjectUtils.isEmpty(medicarOutputMap.get("output")) ? (Map<String, Object>) medicarOutputMap.get("output2") : (Map<String, Object>) medicarOutputMap.get("output");
        Map<String, Object> setlinfoMap = ObjectUtils.isEmpty(outputMap.get("setlinfo")) ? (Map<String, Object>)outputMap.get("result") : (Map<String, Object>)outputMap.get("setlinfo");
        List<Map<String, Object>> setldetailList = (List<Map<String, Object>>) outputMap.get("setldetail");

        String jslx = "";
        String medType = inputDateMap.get("med_type").toString();
        jslx = StringUtils.equals("12",medType) ? "1":"2";
        infno =medicarLogMap.get("INFNO").toString();

        //判断infno 是什么交易 住院就补 gjyb_jsjl_zy 门诊就补 gjyb_jsjl_mz 共济就补 gjyb_jsjl_gj
        if (infno.equals("2207A") || infno.equals("2207")) {
            saveGjybJsjlMz(setlinfoMap,medicarInputMap,setldetailList,req,jslx,infno);
        }else if (infno.equals("S2101")){
            saveGjybJsjlGj(setlinfoMap,medicarInputMap,req,jslx,infno);
        }else if (infno.equals("2304A")){
            saveGjybJsjlZy(setlinfoMap,medicarInputMap,setldetailList,req,jslx,infno);
        }else {
            throw new Exception("获取医保的交易编号不正确目前只支持[2207A/2304A/S2101]");
        }

        return getSuccess(null);
    }
    public void saveGjybJsjlZy(Map<String, Object> setlinfoMap,Map<String, Object> medicarInputMap,List<Map<String, Object>> setldetailList,Map<String, Object> req,String jslx,String infno) throws Exception {
        String idJsjl = medicareMapper.getHisUUID2();

        Map<String, Object> gjybJsjlZyMap = new HashMap<>();
        gjybJsjlZyMap.put("ID_JSJL", idJsjl);//主键
        gjybJsjlZyMap.put("MDTRT_ID", setlinfoMap.get("mdtrt_id"));//医保就诊ID
        gjybJsjlZyMap.put("SETL_ID", setlinfoMap.get("setl_id"));//医保结算ID
        gjybJsjlZyMap.put("PSN_NO", setlinfoMap.get("psn_no"));//患者医保编码
        gjybJsjlZyMap.put("PSN_NAME", setlinfoMap.get("psn_name"));//患者姓名
        gjybJsjlZyMap.put("PSN_CERT_TYPE", setlinfoMap.get("psn_cert_type"));//人员证件类型
        gjybJsjlZyMap.put("CERTNO", setlinfoMap.get("certno"));//证件号码
        gjybJsjlZyMap.put("GEND", setlinfoMap.get("gend"));//姓名
        gjybJsjlZyMap.put("NATY", setlinfoMap.get("naty"));//民族
        gjybJsjlZyMap.put("BRDY", setlinfoMap.get("brdy"));//出生日期
        gjybJsjlZyMap.put("AGE", setlinfoMap.get("age"));//年龄
        gjybJsjlZyMap.put("INSUTYPE", setlinfoMap.get("insutype"));//险种
        gjybJsjlZyMap.put("PSN_TYPE", setlinfoMap.get("psn_type"));//人员类别
        gjybJsjlZyMap.put("CVLSERV_FLAG", setlinfoMap.get("cvlserv_flag"));//公务员标志
        gjybJsjlZyMap.put("MDTRT_CERT_TYPE", setlinfoMap.get("mdtrt_cert_type"));//就诊凭证类型
        gjybJsjlZyMap.put("MED_TYPE", setlinfoMap.get("med_type"));//医疗类别
        gjybJsjlZyMap.put("MEDFEE_SUMAMT", setlinfoMap.get("medfee_sumamt"));//医疗总费用
        gjybJsjlZyMap.put("FULAMT_OWNPAY_AMT", setlinfoMap.get("fulamt_ownpay_amt"));//全自费金额
        gjybJsjlZyMap.put("OVERLMT_SELFPAY", setlinfoMap.get("overlmt_selfpay"));//超限价自费费用
        gjybJsjlZyMap.put("PRESELFPAY_AMT", setlinfoMap.get("preselfpay_amt"));//先行自付金额
        gjybJsjlZyMap.put("INSCP_SCP_AMT", setlinfoMap.get("inscp_scp_amt"));//符合政策范围金额
        gjybJsjlZyMap.put("ACT_PAY_DEDC", setlinfoMap.get("act_pay_dedc"));//实际支付起付线
        gjybJsjlZyMap.put("HIFP_PAY", setlinfoMap.get("hifp_pay"));//基本医疗保险统筹基金支出
        gjybJsjlZyMap.put("POOL_PROP_SELFPAY", setlinfoMap.get("pool_prop_selfpay"));//基本医疗保险统筹基金支付比例
        gjybJsjlZyMap.put("CVLSERV_PAY", setlinfoMap.get("cvlserv_pay"));//公务员医疗补助资金支出
        gjybJsjlZyMap.put("HIFES_PAY", setlinfoMap.get("hifes_pay"));//企业补充医疗保险基金支出
        gjybJsjlZyMap.put("HIFMI_PAY", setlinfoMap.get("hifmi_pay"));//居民大病保险资金支出
        gjybJsjlZyMap.put("HIFOB_PAY", setlinfoMap.get("hifob_pay"));//职工大额医疗费用补助基金支出
        gjybJsjlZyMap.put("MAF_PAY", setlinfoMap.get("maf_pay"));//医疗救助基金支出
        gjybJsjlZyMap.put("OTH_PAY", setlinfoMap.get("oth_pay"));//其他支出
        gjybJsjlZyMap.put("FUND_PAY_SUMAMT", setlinfoMap.get("fund_pay_sumamt"));//基金支付总额
        gjybJsjlZyMap.put("PSN_PART_AMT", setlinfoMap.get("psn_part_amt"));//个人负担总金额
        gjybJsjlZyMap.put("ACCT_PAY", setlinfoMap.get("acct_pay"));//个人账户支出
        gjybJsjlZyMap.put("PSN_CASH_PAY", setlinfoMap.get("psn_cash_pay"));//个人现金支出
        gjybJsjlZyMap.put("HOSP_PART_AMT", setlinfoMap.get("hosp_part_amt"));//医院负担金额
        gjybJsjlZyMap.put("BALC", setlinfoMap.get("balc"));//余额
        gjybJsjlZyMap.put("ACCT_MULAID_PAY", setlinfoMap.get("acct_mulaid_pay"));//个人账户共济支付金额
        gjybJsjlZyMap.put("MEDINS_SETL_ID", setlinfoMap.get("medins_setl_id"));//医药机构结算ID
        gjybJsjlZyMap.put("CLR_OPTINS", setlinfoMap.get("clr_optins"));//清算分中心
        gjybJsjlZyMap.put("CLR_WAY", setlinfoMap.get("clr_way"));//清算方式
        gjybJsjlZyMap.put("CLR_TYPE", setlinfoMap.get("clr_type"));//清算类别
        gjybJsjlZyMap.put("SETL_TIME", setlinfoMap.get("setl_time"));//结算时间
        gjybJsjlZyMap.put("INSUPLC_ADMDVS", medicarInputMap.get("insuplc_admdvs"));//参保地行政区划
        gjybJsjlZyMap.put("ID_ORG", setlinfoMap.get("fixmedins_code"));//机构id
        gjybJsjlZyMap.put("EXP_CONTENT", "补录:住院医保:人工手动补录数据,就诊ID[" + req.get("MDTRT_ID") + "],结算ID[" + req.get("SETL_ID") + "],人员编号[" + req.get("PSN_NO") + "]");//扩展
        int a = medicareMapper.saveGJYBJSJL_ZY(gjybJsjlZyMap);
        if (a==0) throw new Exception("补录gjyb_jsjl_zy失败!");
        if (a>0){
            //写入医保分向信息
            for (Map<String, Object> setldetailMap : setldetailList) {
                setldetailMap.put("id_jsjl",idJsjl);
                setldetailMap.put("id_fxxx",medicareMapper.getHisUUID2());
                a = medicareMapper.saveGJYBJSJL_FXXX_ZY(setldetailMap);
            }
        }
    }
    public void saveGjybJsjlGj(Map<String, Object> setlinfoMap,Map<String, Object> medicarInputMap,Map<String, Object> req,String jslx,String infno) throws Exception {
        String idJsjl = medicareMapper.getHisUUID2();
        Map<String, Object> gjybJsjlGjMap = new HashMap<>();
        gjybJsjlGjMap.put("ID_JSJL", idJsjl);//主键
        gjybJsjlGjMap.put("JSLX", jslx);//结算类型,1挂号,2门诊收费
        gjybJsjlGjMap.put("MDTRT_ID", setlinfoMap.get("mdtrt_id"));//医保就诊ID
        gjybJsjlGjMap.put("SETL_ID", setlinfoMap.get("setl_id"));//医保结算ID
        gjybJsjlGjMap.put("PSN_NO", setlinfoMap.get("psn_no"));//人员编号
        gjybJsjlGjMap.put("PSN_NAME", setlinfoMap.get("psn_name"));//人员姓名
        gjybJsjlGjMap.put("PSN_CERT_TYPE", setlinfoMap.get("psn_cert_type"));//人员证件类型
        gjybJsjlGjMap.put("CERTNO", setlinfoMap.get("certno"));//证件号码
        gjybJsjlGjMap.put("GEND", setlinfoMap.get("gend"));//性别
        gjybJsjlGjMap.put("NATY", setlinfoMap.get("naty"));//民族
        gjybJsjlGjMap.put("BRDY", setlinfoMap.get("brdy"));//出生日期
        gjybJsjlGjMap.put("AGE", setlinfoMap.get("age"));//年龄
        gjybJsjlGjMap.put("INSUTYPE", setlinfoMap.get("insutype"));//险种类型
        gjybJsjlGjMap.put("PSN_TYPE", setlinfoMap.get("psn_type"));//人员类别
        gjybJsjlGjMap.put("CVLSERV_FLAG", setlinfoMap.get("cvlserv_flag"));//公务员标志
        gjybJsjlGjMap.put("MDTRT_CERT_TYPE", setlinfoMap.get("mdtrt_cert_type"));//就诊凭证类型
        gjybJsjlGjMap.put("MED_TYPE", setlinfoMap.get("med_type"));//医疗类别
        gjybJsjlGjMap.put("MEDFEE_SUMAMT", setlinfoMap.get("medfee_sumamt"));//医疗费用总额
        gjybJsjlGjMap.put("ACCT_PAY", setlinfoMap.get("acct_pay"));//个人账户支出
        gjybJsjlGjMap.put("PSN_CASH_PAY", setlinfoMap.get("psn_cash_pay"));//个人现金支出
        gjybJsjlGjMap.put("BALC", setlinfoMap.get("balc"));//余额
        gjybJsjlGjMap.put("MEDINS_SETL_ID", setlinfoMap.get("medins_setl_id"));//医药机构结算ID
        gjybJsjlGjMap.put("CLR_OPTINS", setlinfoMap.get("clr_optins"));//清算分中心
        gjybJsjlGjMap.put("CLR_WAY", setlinfoMap.get("clr_way"));//清算方式
        gjybJsjlGjMap.put("CLR_TYPE", setlinfoMap.get("clr_type"));//清算类别
        gjybJsjlGjMap.put("SETL_TIME", setlinfoMap.get("setl_time"));//结算时间
        gjybJsjlGjMap.put("INSUPLC_ADMDVS", medicarInputMap.get("insuplc_admdvs"));//参保地区划
        gjybJsjlGjMap.put("ID_ORG", setlinfoMap.get("fixmedins_code"));//机构
        gjybJsjlGjMap.put("EXP_CONTENT", "补录:共济医保:人工手动补录数据,就诊ID[" + req.get("MDTRT_ID") + "],结算ID[" + req.get("SETL_ID") + "],人员编号[" + req.get("PSN_NO") + "]");//备注

        int a = medicareMapper.saveGJYBJSJL_GJ(gjybJsjlGjMap);
        if (a==0) throw new Exception("补录gjyb_jsjl_gj失败!");
    }
    public void saveGjybJsjlMz(Map<String, Object> setlinfoMap,Map<String, Object> medicarInputMap,List<Map<String, Object>> setldetailList,Map<String, Object> req,String jslx,String infno) throws Exception {
        String idJsjl = medicareMapper.getHisUUID2();
        //组装医保gjyb_jsjl_mz
        Map<String, Object> gjybJsjlMzMap = new HashMap<>();
        gjybJsjlMzMap.put("ID_JSJL", idJsjl);//32位uuid
        gjybJsjlMzMap.put("JSLX", jslx);//结算类型,1挂号,2门诊收费
        //gjybJsjlMzMap.put("ID_VISMED", null);//hihis就诊ID
        //gjybJsjlMzMap.put("ID_MEDSTIP", null);//hihis结算ID
        gjybJsjlMzMap.put("MDTRT_ID", setlinfoMap.get("mdtrt_id"));//医保就诊ID
        gjybJsjlMzMap.put("SETL_ID", setlinfoMap.get("setl_id"));//医保结算ID
        gjybJsjlMzMap.put("PSN_NO", setlinfoMap.get("psn_no"));//人员编号
        gjybJsjlMzMap.put("PSN_NAME", setlinfoMap.get("psn_name"));//人员姓名
        gjybJsjlMzMap.put("PSN_CERT_TYPE", setlinfoMap.get("psn_cert_type"));//人员证件类型
        gjybJsjlMzMap.put("CERTNO", setlinfoMap.get("certno"));//证件号码
        gjybJsjlMzMap.put("GEND", setlinfoMap.get("gend"));//性别
        gjybJsjlMzMap.put("NATY", setlinfoMap.get("naty"));//民族
        gjybJsjlMzMap.put("BRDY", setlinfoMap.get("brdy"));//出生日期
        gjybJsjlMzMap.put("AGE", setlinfoMap.get("age"));//年龄
        gjybJsjlMzMap.put("INSUTYPE", setlinfoMap.get("insutype"));//险种类型
        gjybJsjlMzMap.put("PSN_TYPE", setlinfoMap.get("psn_type"));//人员类别
        gjybJsjlMzMap.put("CVLSERV_FLAG", setlinfoMap.get("cvlserv_flag"));//公务员标志
        gjybJsjlMzMap.put("MDTRT_CERT_TYPE", setlinfoMap.get("mdtrt_cert_type"));//就诊凭证类型
        gjybJsjlMzMap.put("MED_TYPE", setlinfoMap.get("med_type"));//医疗类别
        gjybJsjlMzMap.put("MEDFEE_SUMAMT", setlinfoMap.get("medfee_sumamt"));//医疗费用总额
        gjybJsjlMzMap.put("FULAMT_OWNPAY_AMT", setlinfoMap.get("fulamt_ownpay_amt"));//全自费金额
        gjybJsjlMzMap.put("OVERLMT_SELFPAY", setlinfoMap.get("overlmt_selfpay"));//超限价自费费用
        gjybJsjlMzMap.put("PRESELFPAY_AMT", setlinfoMap.get("preselfpay_amt"));//先行自付金额
        gjybJsjlMzMap.put("INSCP_SCP_AMT", setlinfoMap.get("inscp_scp_amt"));//符合政策范围金额
        gjybJsjlMzMap.put("ACT_PAY_DEDC", setlinfoMap.get("act_pay_dedc"));//实际支付起付线
        gjybJsjlMzMap.put("HIFP_PAY", setlinfoMap.get("hifp_pay"));//基本医疗保险统筹基金支出
        gjybJsjlMzMap.put("POOL_PROP_SELFPAY", setlinfoMap.get("pool_prop_selfpay"));//基本医疗保险统筹基金支付比例
        gjybJsjlMzMap.put("CVLSERV_PAY", setlinfoMap.get("cvlserv_pay"));//公务员医疗补助资金支出
        gjybJsjlMzMap.put("HIFES_PAY", setlinfoMap.get("hifes_pay"));//企业补充医疗保险基金支出
        gjybJsjlMzMap.put("HIFMI_PAY", setlinfoMap.get("hifmi_pay"));//居民大病保险资金支出
        gjybJsjlMzMap.put("HIFOB_PAY", setlinfoMap.get("hifob_pay"));//职工大额医疗费用补助基金支出
        gjybJsjlMzMap.put("MAF_PAY", setlinfoMap.get("maf_pay"));//医疗救助基金支出
        gjybJsjlMzMap.put("OTH_PAY", setlinfoMap.get("oth_pay"));//其他支出
        gjybJsjlMzMap.put("FUND_PAY_SUMAMT", setlinfoMap.get("fund_pay_sumamt"));//基金支付总额
        gjybJsjlMzMap.put("PSN_PART_AMT", setlinfoMap.get("psn_part_amt"));//个人负担总金额
        gjybJsjlMzMap.put("ACCT_PAY", setlinfoMap.get("acct_pay"));//个人账户支出
        gjybJsjlMzMap.put("PSN_CASH_PAY", setlinfoMap.get("psn_cash_pay"));//个人现金支出
        gjybJsjlMzMap.put("HOSP_PART_AMT", setlinfoMap.get("hosp_part_amt"));//医院负担金额
        gjybJsjlMzMap.put("BALC", setlinfoMap.get("balc"));//余额
        gjybJsjlMzMap.put("ACCT_MULAID_PAY", setlinfoMap.get("acct_mulaid_pay"));//个人账户共济支付金额
        gjybJsjlMzMap.put("MEDINS_SETL_ID", setlinfoMap.get("medins_setl_id"));//医药机构结算ID
        gjybJsjlMzMap.put("CLR_OPTINS", setlinfoMap.get("clr_optins"));//清算经办机构
        gjybJsjlMzMap.put("CLR_WAY", setlinfoMap.get("clr_way"));//清算方式
        gjybJsjlMzMap.put("CLR_TYPE", setlinfoMap.get("clr_type"));//清算类别
        gjybJsjlMzMap.put("SETL_TIME", setlinfoMap.get("setl_time"));//结算时间
        gjybJsjlMzMap.put("INSUPLC_ADMDVS", medicarInputMap.get("insuplc_admdvs"));//参保地行政区域编码
        //gjybJsjlMzMap.put("ID_MEDSTOE", setlinfoMap.get("balc"));//hihis结算ID
        //gjybJsjlMzMap.put("MSG_ID", null);//医保结算id
        gjybJsjlMzMap.put("ID_ORG", medicarInputMap.get("fixmedins_code"));//机构ID fixmedins_code
        gjybJsjlMzMap.put("EXP_CONTENT", "补录:门诊医保:人工手动补录数据,就诊ID[" + req.get("MDTRT_ID") + "],结算ID[" + req.get("SETL_ID") + "],人员编号[" + req.get("PSN_NO") + "]");//扩展字段 备注信息
        //gjybJsjlMzMap.put("MULAID_FLAG", setlinfoMap.get("balc"));//共济标志
        //gjybJsjlMzMap.put("MULAID_SETLID", setlinfoMap.get("balc"));//共济结算ID

        int a = medicareMapper.saveGJYBJSJL_MZ(gjybJsjlMzMap);
        if (a==0) throw new Exception("补录gjyb_jsjl_mz失败!");
        if (a>0){
            //写入医保分向信息
            for (Map<String, Object> setldetailMap : setldetailList) {
                setldetailMap.put("id_jsjl",idJsjl);
                setldetailMap.put("id_fxxx",medicareMapper.getHisUUID2());
                a = medicareMapper.saveGJYBJSJL_FXXX_MZ(setldetailMap);
            }
        }

    }

}
